/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! CHECKER      Replace LoadFromConstantPool by LoadObjFromConst, JIT mode
//! RUN          options: "--compiler-hotness-threshold=1 --no-async-jit=true --compiler-regex='_GLOBAL::.*define_.'", entry: "_GLOBAL::func_main_0"
//! METHOD       "define_f"
//! PASS_AFTER   "IrBuilder"
//! INST         "LoadConstantPool"
//! INST_NEXT    "LoadFromConstantPool"
//! INST_NEXT    "Intrinsic.DefineNCFuncDyn"
//! PASS_AFTER   "Codegen"
//! INST_NOT     "LoadConstantPool"
//! INST_NOT     "LoadFromConstantPool"
//! INST_NOT     "LoadArrayI"
//! INST         /LoadImmediate.*constpool/
//! INST_NEXT    "LoadObjFromConst"
//! INST_NEXT    "Intrinsic.DefineNCFuncDyn"
//!
//! METHOD       "call_define_f"
//! PASS_AFTER   "IrBuilder"
//! INST_COUNT   "LoadConstantPool", 1
//! INST_NOT     "LoadFromConstantPool"
//! INST_NOT     "Intrinsic.DefineNCFuncDyn"
//! PASS_AFTER   "Inline."
//! INST_COUNT   "LoadConstantPool", 2
//! INST         "LoadFromConstantPool"
//! INST         "Intrinsic.DefineNCFuncDyn"
//! PASS_AFTER   "Codegen"
//! INST_NOT     "LoadConstantPool"
//! INST_NOT     "LoadFromConstantPool"
//! INST_COUNT   /LoadImmediate.*constpool/, 1 # VN applied
//! INST         "LoadObjFromConst"
//! INST_NEXT    "Intrinsic.DefineNCFuncDyn"
//!
//! METHOD       "call_define_g"
//! PASS_AFTER   "Inline."
//! INST_COUNT   "LoadConstantPool", 2
//! INST         "LoadFromConstantPool"
//! INST         "Intrinsic.DefineNCFuncDyn"
//! PASS_AFTER   "Codegen"
//! INST_NOT     "LoadConstantPool"
//! INST_NOT     "LoadFromConstantPool"
//! INST_COUNT   /LoadImmediate.*constpool/, 2 # VN not applied
//! INST         "LoadObjFromConst"
//! INST_NEXT    "Intrinsic.DefineNCFuncDyn"

//! CHECKER      Replace LoadFromConstantPool by LoadArrayI, AOT mode
//! RUN_PAOC     options: "--compiler-regex='_GLOBAL::define_f'"
//! METHOD       "define_f"
//! PASS_AFTER   "IrBuilder"
//! INST         "LoadConstantPool"
//! INST_COUNT   "LoadFromConstantPool", 2
//! PASS_AFTER   "Codegen"
//! INST_NOT     "LoadFromConstantPool"
//! INST         "LoadConstantPool"
//! INST_NEXT    "LoadArrayI"
//! INST_NEXT    "Intrinsic.DefineNCFuncDyn"
//! INST_NEXT    "LoadArrayI"
//! INST_NEXT    "Intrinsic.StObjByName"
//! RUN          options: "--compiler-enable-jit=false", entry: "_GLOBAL::func_main_0"

function define_f(z) {
    globalThis.f = (x, y) => x + y + z;
}

function call_define_f(z) {
    define_f(z * 2);
}

// define function inside eval so it has different panda file and different ConstantPool
eval("function define_g(z) {globalThis.g = (x, y) => x + y - z;}");

function call_define_g(z) {
    define_g(z * 2);
}

for (let i = 1; i < 3; i++) {
    define_f(i);
    if (f(1, 2) != i + 3) {
        throw "wrong result for LoadFromConstantPool";
    }
}
for (let i = 1; i < 3; i++) {
    call_define_f(i);
    if (f(1, 2) != i * 2 + 3) {
        throw "wrong result for inlined function";
    }
}
for (let i = 1; i < 3; i++) {
    call_define_g(i);
    if (g(1, 2) != 3 - i * 2) {
        throw "wrong result for inlined function with different ConstantPool";
    }
}
